package com.walterlife.javacore;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;

class Node {
    public int val;
    public Node next;

    Node(int val) {
        this.val = val;
        next = null;
    } 
} 

// FILO
class Stack {
    Node top;

    public Node peek() {
        if(top != null) {
            return top;
        } 
        return null;
    } 

    public Node pop() {
        if(top == null) {
            return null;
        } 
        Node tmp = new Node(top.val);

        // 删除结点
        Node del = top;
        del = null;

        top = top.next;
        return tmp;
    } 

    public void push(Node n) {
        if(n != null) {
            n.next = top;
            top = n;
        } 
    } 
} 

class Queue {
    Node first, last;

    public void enqueue(Node n) {
        if(last == null) {
            last = n;
        } else {
            last.next = n;
            last = n;
            first = last;
        } 
    } 

    public Node dequeue() {
        if(first == null) {
            return null;
        } 
        Node tmp = new Node(first.val);

        Node del = first;
        del = null;

        first = first.next;
        //if(first == null) {
            //last = null;
        //} 

        return tmp;
    } 
} 

class TaskA implements Runnable {
    // AtomicInteger 内部有同步操作
    public static AtomicInteger num = new AtomicInteger(0);

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(num.get() < 1000000) {
            num.incrementAndGet();
            System.out.printf("%s,%d\n", Thread.currentThread().getName(), num.get());
        }
    }
} 

class MyCallable implements Callable<Integer> {
    public Integer call() throws Exception {
        System.out.println("Thread Exectute Here");
        return 1;
    } 
} 

public class App 
{
    public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
          //new Thread() {
            //public void run() {
                //test();  
            //} 
        //}.run();

        //System.out.println("World");
        //

        //testThread();

        //System.out.println(System.getProperties().getProperty("os.name"));
        //testSort(); 
        //testLinkList();
        //testValPass();
        //testIO();
        //testListFiles("/home/walter/workspace/code/java-code/JavaCore");
        //testExector();
        
        //testCollection();

        //new Thread(new TaskA(), "Task One").start();
        //new Thread(new TaskA(), "Task Two").start();
        //new Thread(new TaskA(), "Task Three").start();
        //new Thread(new TaskA(), "Task Four").start();
        //new Thread(new TaskA(), "Task Five").start();
        //new Thread(new TaskA(), "Task Six").start();
        //new Thread(new TaskA(), "Task Seven").start();
        //new Thread(new TaskA(), "Task Eight").start();
        Map m = null;
        System.out.println(m);
    }

    public static void testExector() throws InterruptedException {
        //ExecutorService ec = Executors.newSingleThreadExecutor();
        //ExecutorService ec = Executors.newFixedThreadPool(10);
        //ec.execute(new Runnable() {
            //@Override
            //public void run() {
                //// TODO Auto-generated method stub
                //System.out.println("sss");
                //try {
                    //Thread.sleep(10000000);
                //} catch (InterruptedException e) {
                    //// TODO Auto-generated catch block
                    //e.printStackTrace();
                //}
            //}
        //});
        Thread.sleep(10000000);
    } 

    public static void testCollection() {
        Map<String, String> nameInfo = new HashMap<String, String>();
        nameInfo.put("walter", "mm");
        nameInfo.put("aw", "yyy");
        nameInfo.put("ded", "33yy");
        nameInfo.put("332", "yeyy");

        List<Entry<String, String>> aList = new LinkedList<Entry<String, String>>(nameInfo.entrySet());
        Collections.sort(aList, new Comparator<Entry<String, String>>() {

            @Override
            public int compare(Entry<String, String> o1, Entry<String, String> o2) {
                // TODO Auto-generated method stub
                return (o1.getKey().compareTo(o2.getKey()));
            }
        });
    
        Map<String, String> nameSort = new LinkedHashMap<String, String>();

        for(Entry<String, String> entry: aList) {
            nameSort.put(entry.getKey(), entry.getValue());
        } 

        // from keyset to get valueset
        //for(String k: nameInfo.keySet()) {
            //System.out.printf("key %s value %s\n", k, nameInfo.get(k));
        //} 

        for(Entry<String, String> entry: nameSort.entrySet()) {
            System.out.printf("key: %s value: %s\n", entry.getKey(), entry.getValue());
        } 
    } 

    public static void testListFiles(String path) {
        if(path == null) {
            return;
        } 

        if(!path.endsWith("/")) {
            path += "/";
        } 

        File f = new File(path);
        if(f.isDirectory()) {
            // 不可读时不会报错
            for(File file: f.listFiles()) {
                String name = file.getAbsolutePath();
                if(file.isDirectory() && file.canRead()) {
                    testListFiles(name);
                } else {
                    System.out.println(name);
                } 
            } 
        } else if(f.exists()) {
            System.out.println(f.getAbsolutePath());
        } else {
            return;
        } 
    } 

    public static void testIO() throws IOException {
        //PrintWriter pt = new PrintWriter(new FileWriter("
        String fileName = "input.txt";
        // File 传入路径名后，就可以对改对象进行相关的IO操作了
        try( PrintWriter pt = new PrintWriter(new FileWriter(new File(fileName))) ) {
            pt.write("Hello World");
            pt.write("1323");
            pt.flush();
        }
        //pt.close();
    } 

    public static void testValPass() {
        StringBuffer sb = new StringBuffer("Hello ");
        System.out.println("Before change, sb = " + sb);
        changeData(sb);
        System.out.println("After changeData(n), sb = " + sb);
    }

    public static void changeData(StringBuffer strBuf) {
        StringBuffer sb2 = new StringBuffer("Hi ");
        strBuf = sb2;
        sb2.append("World!");
    }

    public static void testStack() {

    } 

    public static void testLinkList() {
        Node head = new Node(1);
        Node node1 = new Node(2);
        head.next = node1;
        Node node2 = new Node(3);
        node1.next = node2;
        Node node3 = new Node(4);
        node2.next = node3;
        Node node4 = new Node(5);
        node3.next = node4;
        
        System.out.println("before delete n node");
        printList(head);

        //printList(revserseList(head));
        head = deleteNNode(head, 2);

        System.out.println("after delete n node");
        if(head == null) {
            System.out.println("list is empty");
        } else {
            printList(head);
        } 
    } 

    /**
     * 删除链表倒数第 N 个节点
     * 使用快慢指针解决
     * @param head
     * @param n
     * @return 删除节点后的头结点(因为java中是值传递，所以必须将方法内改变的head值返回)
     */
    public static Node deleteNNode(Node head, int n) {
        if(head == null && n < 0) {
            return head;
        } 
        
        if(n == 0) {
            return head;
        } 

        Node slow = head;
        Node fast = head;
        Node tmp = slow;

        // 快指针开始遍历
        while( (fast != null) && n > 0) {
            fast = fast.next; 
            n--;
        } 

        // 节点总数小于 n
        if(n > 0) {
            return head;
        } 
        
        // 节点个数刚好是n,直接删除头结点, 可能导致head 为空(n = 1, list_num = 1)
        if(fast == null) {
            head = slow.next;
            // jvm 回收
            slow = null;
            return head;
        } 

        // 快慢指针同时遍历
        while(fast != null) {
            tmp = slow;
            slow = slow.next;
            fast = fast.next;
        } 

        // 删除slow节点
        tmp.next = slow.next;
        // jvm 回收
        slow = null;
        
        return head;
    } 

    /**
     *
     *
     * @param head
     * @return
     */
    public static Node revserseList(Node head) {
        if(head == null) {
            return null;
        } 
        
        // 一个节点可以不用判断，但是判断下可以减少很多语句的执行
        if(head.next == null) {
            return head;
        } 

        Node before = head;
        Node h = before.next;
        Node after = null;
        before.next = null;

        while(h != null) {
            after = h.next;
            h.next = before;
            before = h;
            h = after;
        } 

        // 返回逆转后的单链表头结点
        return before;
    } 

    public static void printList(Node head) {
        if(head == null) {
            return;
        } 

        Node tmp = head;
        while(tmp != null) {
            System.out.println(tmp.val);
            tmp = tmp.next;
        } 
    } 

    public static void testSort() {
        int[] array = {10, 2, 1, 4, 3, 8, 7, 6};
        quickSort(array, 0, array.length-1);
        for(int v: array) {
            System.out.println(v);
        } 
    } 
    
    // 快速排序
    public static void quickSort(int[] array, int low, int high) {
        if(array == null || low < 0 || high < 0 || high < low) {
            return;
        } 

        int pivot = array[low];
        int iLow = low, jHigh = high;

        // 直到 iLow == jHigh 停止循环 注意 <
        while(iLow < jHigh) {
            // 首先从数组右边开始遍历 注意 >= 
            while(iLow < jHigh && array[jHigh] >= pivot) {
                jHigh--;
            } 
            // 填坑
            if(iLow < jHigh) {
                array[iLow++] = array[jHigh];
            } 

            // 再从左边开始遍历
            while(iLow < jHigh && array[iLow] < pivot){
                iLow++;
            } 
            // 填坑
            if(iLow < jHigh) {
                array[jHigh--] = array[iLow];
            } 
        } 
        array[iLow] = pivot;
        // 注意 iLow - 1
        quickSort(array, low, iLow - 1);
        // 注意 iLow + 1
        quickSort(array, iLow + 1, high);
    } 

    public static void testProcess() {

    } 

    public static void testDameonThread() {
        Thread daemon = new Thread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub

            }
        });

        daemon.setDaemon(true);
        daemon.start();
    } 

    public static void testThread() throws InterruptedException, ExecutionException {
        FutureTask<Integer> task = new FutureTask<Integer>(new MyCallable());
        Thread t = new Thread(task);

        t.start();
        System.out.println(task.get());
    } 

    public static void test() {
        System.out.println("Hello");
    } 
}
